package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql" // init()
)

var db *sql.DB	// 是一个连接池对象

type user struct{
	id int
	name string
	age int
}

func initDB() (err error){
	// 数据库信息
	// 用户名:密码@tcp(ip:端口)/数据库的名字
	dsn := "go:go@tcp(127.0.0.1:3306)/goday"
	// 连接数据库
	db, err = sql.Open("mysql", dsn)	// 不会校验用户名和密码是否正确
	if err != nil{	// dsn格式不正确的时候会报错
		return
	}
	err = db.Ping()	// 尝试连接数据库
	if err != nil{
		return
	}

	db.SetMaxOpenConns(10)	// 设置数据库连接池的最大连接数
	db.SetMaxIdleConns(5)	// 设置最大空闲连接数
	return
}

func transactionDemo(){
	tx, err := db.Begin()
	if err != nil{
		fmt.Printf("begin failed,err: %v\n", err)
		return
	}
	// 执行多个SQL操作
	sqlStr1 := `update user set age=age-2 where id=1`
	sqlStr2 := `update user set age=age+2 where id=`
	// 执行SQL1
	_, err = tx.Exec(sqlStr1)
	if err != nil{
		// 要回滚
		tx.Rollback()
		fmt.Println("执行SQL1出错啦，要回滚")
		return
	}
	// 执行SQL2
	_, err = tx.Exec(sqlStr2)
	if err != nil{
		// 要回滚
		tx.Rollback()
		fmt.Println("执行SQL2出错啦，要回滚")
		return
	}
	// 上面两步SQL都执行成功，就提交本次事务
	err = tx.Commit()
	if err != nil{
		tx.Rollback()
		fmt.Println("提交出错啦，要回滚")
		return
	}
	fmt.Println("事务执行成功!")
}

func main(){
	err := initDB()
	if err != nil{
		fmt.Printf("init DB failed, err: %v\n", err)
		return
	}
	fmt.Println("连接数据库成功！")
	transactionDemo()
}